package com.edol.painting.widget;

import android.content.Context;
import android.graphics.BitmapShader;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Paint.Style;
import android.graphics.PorterDuff.Mode;
import android.graphics.Rect;
import android.graphics.Shader;
import android.graphics.Shader.TileMode;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.ShapeDrawable;
import android.graphics.drawable.shapes.OvalShape;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewConfiguration;

import com.edol.painting.PainterConfig;
import com.edol.painting.R;

import java.util.ArrayList;

public class TexturePickView extends View {

    private static final String TAG = "TexturePickView";

    private int mColumnCount = 5;
    private int mRowCount = 4;
    private int mRingRadius;

    private int mWidth = getResources().getDimensionPixelSize(R.dimen.texture_width);
    private int mHeight = getResources().getDimensionPixelSize(R.dimen.texture_height);

    private int mChildWidth;
    private int mChildHeight;

    private int mChildCount = 20;
    private int mHorizontalSpace = 20;
    private int mVerticalSpace = 20;

    private ShapeDrawable mCicleDrawable = null;

    private Rect mItemRect = new Rect();
    Rect mViewRect = new Rect();

    private int mTouchSlope = 5;
    
    private int mBitmapColor;

    public void setChildWidth(int w) {
    	mChildWidth = w;
    }
    
    public void setChildHeight(int h) {
    	mChildHeight = h;
    }
    
    public TexturePickView(Context context) {
        super(context);
        init();
    }

    public TexturePickView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init();
    }

    public TexturePickView(Context context, AttributeSet attrs) {
        super(context, attrs);
        init();
    }

    private void init() {
        mPaint.setColor(Color.DKGRAY);
        mPaint.setStyle(Style.STROKE);
        mPaint.setStrokeWidth(5);
        mPaint.setAlpha(153);
        mCicleDrawable = new ShapeDrawable(new OvalShape());
        mTouchSlope  = ViewConfiguration.get(getContext()).getScaledTouchSlop();

        loadShader();
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        setMeasuredDimension(measureWidth(widthMeasureSpec), measureHeight(heightMeasureSpec));
       /* mHorizontalSpace = 25;
        mVerticalSpace = 20;*/

        /*mChildWidth = (width - getPaddingLeft() - getPaddingRight() - (mColumnCount - 1) * mHorizontalSpace) / mColumnCount;
        mChildHeight = (height - getPaddingTop() - getPaddingBottom() - (mRowCount - 1) * mVerticalSpace) / mRowCount;

        if (mChildWidth > mChildHeight) {
            mChildWidth = mChildHeight;
        	mChildHeight = mChildWidth;
            mHorizontalSpace = (width - getPaddingLeft() - getPaddingRight() - mColumnCount * mChildWidth) / (mColumnCount - 1);
        } else if (mChildWidth < mChildHeight) {
            mChildHeight = mChildWidth;
            mChildWidth = mChildHeight;
            mVerticalSpace = (height - getPaddingTop() - getPaddingBottom() - mRowCount * mChildHeight) / (mRowCount - 1);
        }
        Log.i(TAG, "onMeasure()--width="  + width + ", height=" + height + ",child width=" + mChildWidth + ", mChildHeight="+mChildHeight);*/
    }

    private int measureHeight(int heightMeasureSpec) {
        int heightSpecMode = MeasureSpec.getMode(heightMeasureSpec);
        if (heightSpecMode == MeasureSpec.EXACTLY) {
            return MeasureSpec.getSize(heightMeasureSpec);
        } else {
            return Math.min(getPaddingTop() + mHeight + getPaddingBottom(), MeasureSpec.getSize(heightMeasureSpec));
        }
    }

    private ArrayList<BitmapShader> mShaders = new ArrayList<BitmapShader>();
    private void loadShader() {
    	mHeight = getResources().getDimensionPixelSize(R.dimen.texture_container_height);
    	mChildWidth = getResources().getDimensionPixelSize(R.dimen.texture_child_size);
        mChildHeight = mChildWidth;
    	mHorizontalSpace = getResources().getDimensionPixelSize(R.dimen.texture_horizontal_space);
    	mVerticalSpace = getResources().getDimensionPixelSize(R.dimen.texture_vertical_space);
    	mRingRadius = getResources().getDimensionPixelSize(R.dimen.texture_ring_radius);
        for (int i = 0; i < mChildCount; i++) {
            int id = getResources().getIdentifier("fill_" + i, "drawable", PainterConfig.PACKAGE_NAME);
            if (id > 0) {
                BitmapDrawable drawable = (BitmapDrawable)getResources().getDrawable(id);
                mShaders.add(new BitmapShader(drawable.getBitmap(), TileMode.REPEAT, TileMode.REPEAT));
            } else {
                break;
            }
        }
    }

    public BitmapShader getCurrentTexture() {
        return mShaders.get(mSelectIndex);
    }
    
    public void setBitmapColor(int color) {
    	mBitmapColor = color;
    }

    private int measureWidth(int widthMeasureSpec) {
        int widthSpecMode = MeasureSpec.getMode(widthMeasureSpec);
        if (widthSpecMode == MeasureSpec.EXACTLY) {
            return MeasureSpec.getSize(widthMeasureSpec);
        } else {
            return Math.min(getPaddingLeft() + mWidth + getPaddingRight(), MeasureSpec.getSize(widthMeasureSpec));
        }
    }

    private Paint mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
    @Override
    protected void onDraw(Canvas canvas) {
        for (int i = 0; i < mChildCount; i++) {
        	int l = i % mColumnCount;
            int n = i / mColumnCount;
            int left = getPaddingLeft() + l * mChildWidth + l * mHorizontalSpace;
            int top = getPaddingTop() + n * mChildHeight + n * mVerticalSpace;
            mItemRect.set(left, top, left + mChildWidth, top + mChildHeight);

            mCicleDrawable.setBounds(mItemRect);
            mCicleDrawable.setColorFilter(mBitmapColor, Mode.SRC_IN);
            if (i < mShaders.size() && mShaders.get(i) != null) {
            	mCicleDrawable.getPaint().setShader(mShaders.get(i));
            } else {
                mCicleDrawable.getPaint().setShader(null);
            }
            mCicleDrawable.draw(canvas);

            if (mSelectIndex == i) {
                mPaint.setColor(mBitmapColor);
                canvas.drawCircle(mItemRect.left + mChildWidth / 2 , mItemRect.top + mChildHeight / 2, mRingRadius, mPaint);
            }
        }
    }

    private int mClickX,mClickY;
    private boolean isClick = false;
    private int mSelectIndex = 0;
    @Override
    public boolean onTouchEvent(MotionEvent event) {
        int action = event.getAction();
        int x = (int)event.getX();
        int y = (int)event.getY();
        if (action == MotionEvent.ACTION_DOWN) {
            mClickX = x;
            mClickY = y;
            isClick = true;
        } else if (action == MotionEvent.ACTION_MOVE) {
            if (Math.abs(x - mClickX) >= mTouchSlope
                    || Math.abs(y - mClickY) >= mTouchSlope){
                isClick = false;
            }
        } else if (action == MotionEvent.ACTION_UP) {
            if (isClick) {
                int index = getItemIndex(mClickX, mClickY);
                if (index >= 0 && mSelectIndex != index) {
                    mSelectIndex = index;
                    if (mListener != null) {
                        mListener.onTextureChildClick(mSelectIndex, mSelectIndex < mShaders.size() ? mShaders.get(mSelectIndex) : null);
                    }
                    invalidate();
                }
            }
        }
        return true;
    }

    public int getSelectIdx() {
        return mSelectIndex;
    }

    private int getItemIndex (int x, int y) {
        int width = getMeasuredWidth() / mColumnCount;
        int height = getMeasuredHeight() / mRowCount;

        int column = x / width;
        int row = y / height;

        int index = row * mColumnCount + column;
        if (index >= mChildCount || index < 0) {
            index = -1;
        } else {
            int l = index % mColumnCount;
            int n = index / mColumnCount;
            int left = getPaddingLeft() + l * mChildWidth + l * mHorizontalSpace;
            int top = getPaddingTop() + n * mChildHeight + n * mVerticalSpace;

            Rect rect = new Rect();
            rect.set(left, top, left + mChildWidth, top + mChildHeight);

            if (!rect.contains(x, y)) {
                index = -1;
            }
        }

        return index;
    }
    
    public interface OnChildClickListener {
        void onTextureChildClick(int position, Shader shader);
    }

    private OnChildClickListener mListener;
    public void setOnChildClickListener(OnChildClickListener listener) {
        mListener = listener;
    }

    public void setSelectIdx(int initIdx) {
        mSelectIndex = initIdx;
    }

}
